package com.gitee.huanminabc.dynamicdb.core;

import com.gitee.huanminabc.dynamicdb.common.DynamicDbException;
import com.gitee.huanminabc.dynamicdb.common.SpringContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.util.Stack;
/**
 * @author huanmin
 * @date 2024/11/22
 */
@Slf4j
public class TransactionalManage {


    

    /**
     * 开启事务处理方法, 采用的是如果之前有事务就加入，如果没有就创建新事务
     * key:数据源的key
     */
    public static TransactionStatus openTransaction() {
        // 从Spring上下文中获取事务管理器
        try {
            DataSourceTransactionManager dataSourceTransactionManager =(DataSourceTransactionManager) SpringContextHolder.getBean(TransactionManager.class);
            // 创建新的事务状态
            DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
            //必须使用这种方式才允许一个线程中出现不同数据源多个事务
            //如果用PROPAGATION_REQUIRED加入别的事务,那么就会使用别的事务内的数据源提交
            //最后会导致找不到表
            defaultTransactionDefinition.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
            TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(defaultTransactionDefinition);
            // 将事务状态和事务管理器存入对应的栈中
            addTransactionManager(transactionStatus,dataSourceTransactionManager);
            addDeepTransaction();
            return transactionStatus;
        } catch (Exception e) {
            throw new DynamicDbException(e,"开启事务失败");
        }

    }

    /**
     * 提交处理方法
     */
    public  static  void commit() {
        subDeepTransaction();
        if (isDeepTransactionEmpty()){
            // 循环，直到事务管理器栈为空
            while (! DBContext.stack.get().isEmpty()) {
                // 从事务管理器栈和事务状态栈中分别弹出当前的事务管理器和事务状态
                // 提交当前事务状态
                DBContext.transaction.get().pop()
                        .commit( DBContext.stack.get().pop());

            }
            clearTransaction();
        }
    }


    /**
     * 回滚处理方法
     */
    public static  void rollback() {
        subDeepTransaction();
        if (isDeepTransactionEmpty()){
            // 循环，直到事务管理器栈为空
            while (!DBContext.stack.get().isEmpty()) {
                // 从事务管理器栈和事务状态栈中分别弹出当前的事务管理器和事务状态
                // 回滚当前事务状态
                DBContext.transaction.get().pop().rollback(DBContext.stack.get().pop());
            }
           clearTransaction();
        }
    }

    //只清理事务的
    public static void clearTransaction() {
        DBContext.stack.remove();
        DBContext.transaction.remove();
        DBContext.deepTransaction.remove();
        log.info("clearTransaction数据源事务数据清理完成{}", Thread.currentThread().getName());
    }

    //deepTransaction++
    public static void addDeepTransaction() {
        DBContext.deepTransaction.set(DBContext.deepTransaction.get() == null ? 1 : DBContext.deepTransaction.get() + 1);
    }

    //deepTransaction--
    public static void subDeepTransaction() {
        DBContext.deepTransaction.set(DBContext.deepTransaction.get() - 1);
    }
    //是空
    public static boolean isDeepTransactionEmpty() {
        return DBContext.deepTransaction.get()!=null&& DBContext.deepTransaction.get() == 0;
    }

    //判断是否存在事务，如果存在返回true
    public static boolean hasTransaction() {
        return DBContext.stack.get() != null && !DBContext.stack.get().isEmpty();
    }

    public  static  void creatNewTransaction(){
        //如果当前线程已经存在事务管理器，就不再创建
        if (DBContext.stack.get() != null) {
            return;
        }
        //存放事务管理器的栈
        Stack<DataSourceTransactionManager> dataSourceTransactionManagerStack = new Stack<>();
        //存放事务的状态，每一个DataSourceTransactionManager 对应一个 TransactionStatus
        Stack<TransactionStatus> transactionStatuStack = new Stack<>();
        DBContext.stack.set(transactionStatuStack);
        DBContext.transaction.set(dataSourceTransactionManagerStack);
    }

    //加入事务管理器
    public static void addTransactionManager(TransactionStatus transactionStatus, DataSourceTransactionManager dataSourceTransactionManager) {
        //如果当前线程不存在事务管理器，就创建
        creatNewTransaction();
        DBContext.stack.get().push(transactionStatus);
        DBContext.transaction.get().push(dataSourceTransactionManager);
    }
}
